/***************************************************************************
 *   Copyright (C) 2007 by Warren Kenny   *
 *   warren.kenny@gmail.com   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/


#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <otaCore.h>
#include <otaConfigReader.h>
#include <otaPacketCapture.h>
#include <otaMySQLPacketProcessor.h>
#include <otaSessionManager.h>
#include <otaStorageEngine.h>
#include <otaMySQLStorageEngine.h>

#ifndef WIN32
#include <unistd.h>
#endif

using namespace std;

void OTACallback( u_char *args, const struct pcap_pkthdr* pkthdr, const u_char* packet )
{
	otaMySQLPacketProcessor *processor = reinterpret_cast<otaMySQLPacketProcessor *>(args);
	const char *data = reinterpret_cast<const char*>( packet );
	processor->process( data, pkthdr->caplen, pkthdr->ts );
}

int main(int argc, char *argv[])
{
	otaConfigReader reader;
	otaPacketCapture captor;
	otaStorageEngine *storage;
	otaMySQLPacketProcessor processor;
	
	bool configSet = false;												// Flags indicating whether a user has diverged from defaults
	bool engineReset = false;
	
	for(int i = 1; i < argc; i++)											// Process command-line arguments
	{
		if(strcmp(argv[i], "-c") == 0 && argc > i)
		{
			string configFile(argv[i+1]);
			if(!reader.readFile(configFile))
			{
				cout << "Unable to open specified configuration file" << endl;
				return 0;
			}
			else 
			{
				i++;
				configSet = true;
			}
		}
		else if(strcmp(argv[i], "-r") == 0)
		{
			engineReset = true;	
		}
		else if(strcmp(argv[i], "-h") == 0)
		{
			cout << "Usage:" << endl << endl;
			cout << "ota" << endl;
			cout << "\"[ -c <configuration file> ]\" - Specify Location of ota Configuration File" << endl;
			cout << "\"[ -r ]\" - Reset Storage Engine" << endl;
			return 0;
		}
	}
#ifndef WIN32
	if(getuid() != 0 && geteuid != 0)
	{
		cout << "You must run Ought to Audit as root" << endl;
		return 0;
	}
	if(!configSet && !reader.readFile())
	{
		cout << "Failed to open default configuration file at '/etc/ota.conf', see \"ota -h\" for usage information, aborting..." << endl;
		return 0;
	}
#else
	if(!configSet && !reader.readFile())
	{
		cout << "Failed to open default configuration file 'ota.conf', see \"ota -h\" for usage information, aborting..." << endl;
		return 0;
	}
#endif
	storage = new otaMySQLStorageEngine();
	
	bool ok = true;
	
	ok = ( 		captor.init( reader ) &&
			storage->init( reader ) &&
			processor.init( reader ) );
	
	if(engineReset)
	{
		if(!storage->reset())
		{
			cout << "Attempt to reset storage engine failed" << endl;
			ok = false;
			return 0;
		}
		else
			cout << "Storage Engine reset successfully" << endl;
	}
	
	if( ok )
	{
		processor.setStorageEngine( storage );
		u_char *arg = reinterpret_cast<u_char *>( &processor );
		std::cout << "Auditing Process Active" << std::endl;
		captor.activateCapture( OTACallback, arg );
	}
	else
	{
		std::cout << "One or more errors occurred, Ought to Audit was unable to start" << std::endl;
	}
	
	delete storage;
	return 0;
	
}
